// src/services/api.ts
import axios from 'axios'
import type { AxiosInstance, AxiosRequestHeaders } from 'axios'

/**
 * API 客户端（Vite 兼容）
 *
 * 使用 Vite 时请在 .env / .env.development 中设置：
 * VITE_API_BASE=https://your.api.base 或 VITE_API_BASE=/api （本地代理）
 */
const API_BASE: string =
  (typeof import.meta !== 'undefined' && (import.meta as any).env?.VITE_API_BASE) || '/api'

const apiClient: AxiosInstance = axios.create({
  baseURL: API_BASE,
  timeout: 15000,
  headers: {
    'Content-Type': 'application/json',
  } as AxiosRequestHeaders,
})

/* ------------------ 拦截器：统一注入 token & 简单错误处理 ------------------ */
apiClient.interceptors.request.use((config) => {
  try {
    const token = localStorage.getItem('auth_token')
    if (token) {
      if (!config.headers) config.headers = {} as AxiosRequestHeaders
      ;(config.headers as AxiosRequestHeaders)['Authorization'] = `Bearer ${token}`
    }
  } catch (err) {
    // ignore (SSR or localStorage inaccessible)
  }
  return config
})

apiClient.interceptors.response.use(
  (resp) => resp,
  (err) => {
    // 可扩展：全局 401 处理、错误上报等
    return Promise.reject(err)
  },
)

/* ------------------ 类型定义（前端约定） ------------------ */
/**
 * 前后端交互时建议后端接收/返回的结构（示例）：
 * Project {
 *   id: string (或 key)
 *   project: string
 *   yearMonth?: "YYYY-MM" | null
 *   tasks?: { [taskKey: string]: Task }
 *   createdAt?: ISOString
 *   updatedAt?: ISOString
 *   deletedAt?: ISOString | null
 * }
 *
 * Task {
 *   person?: string[]   // 始终数组（便于多选）
 *   planMonth?: number | null
 *   planDay?: number | null
 *   actualMonth?: number | null
 *   actualDay?: number | null
 *   state?: 'pending' | 'done' | null
 *   createdAt?: ISOString
 *   updatedAt?: ISOString
 * }
 */
export type StateType = 'pending' | 'done' | null

export interface TaskPayload {
  person?: string[] | null
  planMonth?: number | null
  planDay?: number | null
  actualMonth?: number | null
  actualDay?: number | null
  state?: StateType
  createdAt?: string | null
  updatedAt?: string | null
  deletedAt?: string | null
}

export interface ProjectPayload {
  id?: string // 如果后端使用 id 字段
  key?: string // 或者 key（与你组件里用的 key 对应）
  project: string
  yearMonth?: string | null // 'YYYY-MM'
  tasks?: Record<string, TaskPayload>
  createdAt?: string | null
  updatedAt?: string | null
  deletedAt?: string | null
}

/* ------------------ 辅助：normalize（前/后端字段映射点） ------------------ */
/**
 * 后端返回的 raw 可能与前端结构不同，统一在这里转换到前端使用格式。
 * 若后端已经返回与前端一致的结构，可直接 return raw。
 */
export function normalizeRowFromBackend(raw: any): ProjectPayload {
  // 默认直接返回（按需修改）
  // 示例：如果后端返回 { id, name, ym, tasks }，在这里做映射：
  // return { key: raw.id, project: raw.name, yearMonth: raw.ym, tasks: raw.tasks }
  return raw as ProjectPayload
}

/**
 * 将前端的 row 转为后端期望的格式（例如删除本地-only 字段等）
 */
export function normalizeRowToBackend(row: ProjectPayload): any {
  // 默认直接返回（按需修改）
  return row
}

/* ------------------ 时间戳助手 ------------------ */
function nowIso(): string {
  return new Date().toISOString()
}

/* ------------------ API：清晰注释 + 实现 ------------------ */

/**
 * GET /projects
 * - params: { page, pageSize, yearMonth, q, ... }
 * - 返回示例：{ total: number, data: ProjectPayload[] }
 */
export async function getProjects(params?: Record<string, any>) {
  const res = await apiClient.get<{ total: number; data: any[] }>('/projects', { params })
  return {
    total: res.data.total,
    data: res.data.data.map((r) => normalizeRowFromBackend(r)),
  }
}

/**
 * GET /projects/:id
 * - 返回单个项目
 */
export async function getProject(projectId: string) {
  const res = await apiClient.get<any>(`/projects/${encodeURIComponent(projectId)}`)
  return normalizeRowFromBackend(res.data)
}

/**
 * POST /projects
 * - payload: ProjectPayload（若后端会自动生成 id/createdAt，前端可只传需要的字段）
 * - 前端会在请求体中附带 createdAt/updatedAt（但后端可以覆盖）
 */
export async function createProject(payload: ProjectPayload) {
  const body = normalizeRowToBackend({
    ...payload,
    createdAt: payload.createdAt ?? nowIso(),
    updatedAt: payload.updatedAt ?? nowIso(),
  })
  const res = await apiClient.post<any>('/projects', body)
  return normalizeRowFromBackend(res.data)
}

/**
 * PUT /projects/:id
 * - 用于替换/更新整行（后端应返回更新后的资源）
 * - options.ifUnmodifiedSince: 可用于乐观并发控制（If-Unmodified-Since header 或 ETag）
 */
export async function updateProject(
  projectId: string,
  payload: ProjectPayload,
  options?: { ifUnmodifiedSince?: string },
) {
  const body = normalizeRowToBackend({
    ...payload,
    updatedAt: payload.updatedAt ?? nowIso(),
  })
  const headers: Record<string, string> = {}
  if (options?.ifUnmodifiedSince) headers['If-Unmodified-Since'] = options.ifUnmodifiedSince
  const res = await apiClient.put<any>(`/projects/${encodeURIComponent(projectId)}`, body, {
    headers,
  })
  return normalizeRowFromBackend(res.data)
}

/**
 * PATCH /projects/:projectId/tasks/:taskKey
 * - 局部更新某个任务单元（单元格）
 * - payload: TaskPayload
 * - 返回：更新后的 task（或整个 project，按后端实现）
 *
 * 前端会自动写入 updatedAt；若是创建新 task，建议后端返回 createdAt/updatedAt。
 */
export async function patchTask(projectId: string, taskKey: string, payload: TaskPayload) {
  const body = {
    ...payload,
    updatedAt: payload.updatedAt ?? nowIso(),
  }
  const res = await apiClient.patch<any>(
    `/projects/${encodeURIComponent(projectId)}/tasks/${encodeURIComponent(taskKey)}`,
    body,
  )
  // 假设后端返回 { task: {...} } 或者直接返回 task 对象
  if (res.data && res.data.task) return res.data.task as TaskPayload
  return res.data as TaskPayload
}

/**
 * DELETE /projects/:id
 * - 删除整行
 * - 有的后端实现为软删除（接收 deletedAt），有的直接删除资源
 * - 这里我们直接调用 DELETE；若后端需要 body (如 deletedAt)，请改为 PUT/PATCH 并传递 deletedAt
 */
export async function deleteProject(projectId: string) {
  await apiClient.delete(`/projects/${encodeURIComponent(projectId)}`)
  return true
}

/**
 * DELETE /projects/:projectId/tasks/:taskKey
 * - 删除单元格（任务），后端可实现为将该 task 置为空或删除键
 */
export async function deleteTask(projectId: string, taskKey: string) {
  await apiClient.delete(
    `/projects/${encodeURIComponent(projectId)}/tasks/${encodeURIComponent(taskKey)}`,
  )
  return true
}

/* ------------------ 导出默认对象 ------------------ */
export default {
  apiClient,
  getProjects,
  getProject,
  createProject,
  updateProject,
  patchTask,
  deleteProject,
  deleteTask,
  normalizeRowFromBackend,
  normalizeRowToBackend,
}
